from mcp.server.fastmcp import FastMCP
import redis
import json
import os
from typing import Optional, Dict, Any, List
import logging

# 设置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# 创建Redis MCP服务器实例
mcp = FastMCP("Redis MCP Server")

# 全局Redis连接池
redis_connections: Dict[str, redis.Redis] = {}

# 默认Redis连接配置（可通过环境变量覆盖）
DEFAULT_REDIS_CONFIG = {
    "host": os.getenv("REDIS_HOST", "localhost"),
    "port": int(os.getenv("REDIS_PORT", "6379")),
    "password": os.getenv("REDIS_PASSWORD", None),
    "db": int(os.getenv("REDIS_DB", "0"))
}

def get_redis_connection(host: str, port: int, password: Optional[str] = None, db: int = 0) -> redis.Redis:
    """获取或创建Redis连接
    
    参数:
        host (str): Redis服务器地址
        port (int): Redis服务器端口
        password (str, optional): Redis密码
        db (int): 数据库编号，默认为0
    
    返回:
        redis.Redis: Redis连接对象
    """
    connection_key = f"{host}:{port}:{db}"
    
    if connection_key not in redis_connections:
        try:
            # 创建Redis连接
            redis_conn = redis.Redis(
                host=host,
                port=port,
                password=password,
                db=db,
                decode_responses=True,  # 自动解码响应为字符串
                socket_connect_timeout=5,  # 连接超时
                socket_timeout=5,  # 读取超时
                retry_on_timeout=True
            )
            
            # 测试连接
            redis_conn.ping()
            redis_connections[connection_key] = redis_conn
            logger.info(f"成功连接到Redis服务器: {host}:{port}")
            
        except redis.ConnectionError as e:
            raise Exception(f"无法连接到Redis服务器 {host}:{port}: {str(e)}")
        except redis.AuthenticationError as e:
            raise Exception(f"Redis认证失败: {str(e)}")
        except Exception as e:
            raise Exception(f"Redis连接错误: {str(e)}")
    
    return redis_connections[connection_key]

@mcp.tool()
def redis_set(host: str, port: int, key: str, value: str, password: Optional[str] = None, 
              db: int = 0, expire: Optional[int] = None) -> str:
    """设置Redis键值对
    
    参数:
        host (str): Redis服务器地址
        port (int): Redis服务器端口
        key (str): 键名
        value (str): 值
        password (str, optional): Redis密码
        db (int): 数据库编号，默认为0
        expire (int, optional): 过期时间（秒）
    
    返回:
        str: 操作结果信息
    """
    try:
        redis_conn = get_redis_connection(host, port, password, db)
        
        if expire:
            result = redis_conn.setex(key, expire, value)
        else:
            result = redis_conn.set(key, value)
        
        if result:
            return f"成功设置键 '{key}' = '{value}'" + (f" (过期时间: {expire}秒)" if expire else "")
        else:
            return f"设置键 '{key}' 失败"
            
    except Exception as e:
        return f"设置键值对失败: {str(e)}"

@mcp.tool()
def redis_get(host: str, port: int, key: str, password: Optional[str] = None, db: int = 0) -> str:
    """获取Redis键值
    
    参数:
        host (str): Redis服务器地址
        port (int): Redis服务器端口
        key (str): 键名
        password (str, optional): Redis密码
        db (int): 数据库编号，默认为0
    
    返回:
        str: 键值或错误信息
    """
    try:
        redis_conn = get_redis_connection(host, port, password, db)
        value = redis_conn.get(key)
        
        if value is not None:
            return f"键 '{key}' 的值: {value}"
        else:
            return f"键 '{key}' 不存在"
            
    except Exception as e:
        return f"获取键值失败: {str(e)}"

@mcp.tool()
def redis_delete(host: str, port: int, key: str, password: Optional[str] = None, db: int = 0) -> str:
    """删除Redis键
    
    参数:
        host (str): Redis服务器地址
        port (int): Redis服务器端口
        key (str): 键名
        password (str, optional): Redis密码
        db (int): 数据库编号，默认为0
    
    返回:
        str: 操作结果信息
    """
    try:
        redis_conn = get_redis_connection(host, port, password, db)
        result = redis_conn.delete(key)
        
        if result > 0:
            return f"成功删除键 '{key}'"
        else:
            return f"键 '{key}' 不存在或已被删除"
            
    except Exception as e:
        return f"删除键失败: {str(e)}"

@mcp.tool()
def redis_exists(host: str, port: int, key: str, password: Optional[str] = None, db: int = 0) -> str:
    """检查Redis键是否存在
    
    参数:
        host (str): Redis服务器地址
        port (int): Redis服务器端口
        key (str): 键名
        password (str, optional): Redis密码
        db (int): 数据库编号，默认为0
    
    返回:
        str: 键存在状态信息
    """
    try:
        redis_conn = get_redis_connection(host, port, password, db)
        exists = redis_conn.exists(key)
        
        return f"键 '{key}' {'存在' if exists else '不存在'}"
        
    except Exception as e:
        return f"检查键存在性失败: {str(e)}"

@mcp.tool()
def redis_keys(host: str, port: int, pattern: str = "*", password: Optional[str] = None, db: int = 0) -> str:
    """获取匹配模式的Redis键列表
    
    参数:
        host (str): Redis服务器地址
        port (int): Redis服务器端口
        pattern (str): 键名模式，默认为"*"（所有键）
        password (str, optional): Redis密码
        db (int): 数据库编号，默认为0
    
    返回:
        str: 匹配的键列表
    """
    try:
        redis_conn = get_redis_connection(host, port, password, db)
        keys = redis_conn.keys(pattern)
        
        if keys:
            return f"匹配模式 '{pattern}' 的键: {', '.join(keys)}"
        else:
            return f"没有找到匹配模式 '{pattern}' 的键"
            
    except Exception as e:
        return f"获取键列表失败: {str(e)}"

@mcp.tool()
def redis_ttl(host: str, port: int, key: str, password: Optional[str] = None, db: int = 0) -> str:
    """获取Redis键的剩余生存时间
    
    参数:
        host (str): Redis服务器地址
        port (int): Redis服务器端口
        key (str): 键名
        password (str, optional): Redis密码
        db (int): 数据库编号，默认为0
    
    返回:
        str: 剩余生存时间信息
    """
    try:
        redis_conn = get_redis_connection(host, port, password, db)
        ttl = redis_conn.ttl(key)
        
        if ttl == -1:
            return f"键 '{key}' 没有设置过期时间"
        elif ttl == -2:
            return f"键 '{key}' 不存在"
        else:
            return f"键 '{key}' 剩余生存时间: {ttl} 秒"
            
    except Exception as e:
        return f"获取键生存时间失败: {str(e)}"

@mcp.tool()
def redis_hset(host: str, port: int, name: str, key: str, value: str, 
               password: Optional[str] = None, db: int = 0) -> str:
    """设置Redis哈希字段
    
    参数:
        host (str): Redis服务器地址
        port (int): Redis服务器端口
        name (str): 哈希表名
        key (str): 字段名
        value (str): 字段值
        password (str, optional): Redis密码
        db (int): 数据库编号，默认为0
    
    返回:
        str: 操作结果信息
    """
    try:
        redis_conn = get_redis_connection(host, port, password, db)
        result = redis_conn.hset(name, key, value)
        
        return f"成功设置哈希表 '{name}' 的字段 '{key}' = '{value}'"
        
    except Exception as e:
        return f"设置哈希字段失败: {str(e)}"

@mcp.tool()
def redis_hget(host: str, port: int, name: str, key: str, 
               password: Optional[str] = None, db: int = 0) -> str:
    """获取Redis哈希字段值
    
    参数:
        host (str): Redis服务器地址
        port (int): Redis服务器端口
        name (str): 哈希表名
        key (str): 字段名
        password (str, optional): Redis密码
        db (int): 数据库编号，默认为0
    
    返回:
        str: 字段值或错误信息
    """
    try:
        redis_conn = get_redis_connection(host, port, password, db)
        value = redis_conn.hget(name, key)
        
        if value is not None:
            return f"哈希表 '{name}' 字段 '{key}' 的值: {value}"
        else:
            return f"哈希表 '{name}' 中字段 '{key}' 不存在"
            
    except Exception as e:
        return f"获取哈希字段值失败: {str(e)}"

@mcp.tool()
def redis_hgetall(host: str, port: int, name: str, 
                  password: Optional[str] = None, db: int = 0) -> str:
    """获取Redis哈希表的所有字段和值
    
    参数:
        host (str): Redis服务器地址
        port (int): Redis服务器端口
        name (str): 哈希表名
        password (str, optional): Redis密码
        db (int): 数据库编号，默认为0
    
    返回:
        str: 哈希表的所有字段和值
    """
    try:
        redis_conn = get_redis_connection(host, port, password, db)
        hash_data = redis_conn.hgetall(name)
        
        if hash_data:
            result = f"哈希表 '{name}' 的所有字段和值:\n"
            for key, value in hash_data.items():
                result += f"  {key}: {value}\n"
            return result.strip()
        else:
            return f"哈希表 '{name}' 不存在或为空"
            
    except Exception as e:
        return f"获取哈希表失败: {str(e)}"

@mcp.tool()
def redis_lpush(host: str, port: int, name: str, *values: str, 
                password: Optional[str] = None, db: int = 0) -> str:
    """向Redis列表左侧推入元素
    
    参数:
        host (str): Redis服务器地址
        port (int): Redis服务器端口
        name (str): 列表名
        *values (str): 要推入的值
        password (str, optional): Redis密码
        db (int): 数据库编号，默认为0
    
    返回:
        str: 操作结果信息
    """
    try:
        redis_conn = get_redis_connection(host, port, password, db)
        result = redis_conn.lpush(name, *values)
        
        return f"成功向列表 '{name}' 左侧推入 {len(values)} 个元素，当前列表长度: {result}"
        
    except Exception as e:
        return f"推入列表元素失败: {str(e)}"

@mcp.tool()
def redis_rpop(host: str, port: int, name: str, 
               password: Optional[str] = None, db: int = 0) -> str:
    """从Redis列表右侧弹出元素
    
    参数:
        host (str): Redis服务器地址
        port (int): Redis服务器端口
        name (str): 列表名
        password (str, optional): Redis密码
        db (int): 数据库编号，默认为0
    
    返回:
        str: 弹出的元素或错误信息
    """
    try:
        redis_conn = get_redis_connection(host, port, password, db)
        value = redis_conn.rpop(name)
        
        if value is not None:
            return f"从列表 '{name}' 右侧弹出元素: {value}"
        else:
            return f"列表 '{name}' 为空"
            
    except Exception as e:
        return f"弹出列表元素失败: {str(e)}"

@mcp.tool()
def redis_lrange(host: str, port: int, name: str, start: int = 0, end: int = -1,
                 password: Optional[str] = None, db: int = 0) -> str:
    """获取Redis列表指定范围的元素
    
    参数:
        host (str): Redis服务器地址
        port (int): Redis服务器端口
        name (str): 列表名
        start (int): 起始位置，默认为0
        end (int): 结束位置，默认为-1（最后一个元素）
        password (str, optional): Redis密码
        db (int): 数据库编号，默认为0
    
    返回:
        str: 列表元素
    """
    try:
        redis_conn = get_redis_connection(host, port, password, db)
        elements = redis_conn.lrange(name, start, end)
        
        if elements:
            return f"列表 '{name}' 的元素: {', '.join(elements)}"
        else:
            return f"列表 '{name}' 不存在或为空"
            
    except Exception as e:
        return f"获取列表元素失败: {str(e)}"

@mcp.tool()
def redis_info(host: str, port: int, password: Optional[str] = None, db: int = 0) -> str:
    """获取Redis服务器信息
    
    参数:
        host (str): Redis服务器地址
        port (int): Redis服务器端口
        password (str, optional): Redis密码
        db (int): 数据库编号，默认为0
    
    返回:
        str: Redis服务器信息
    """
    try:
        redis_conn = get_redis_connection(host, port, password, db)
        info = redis_conn.info()
        
        # 格式化输出重要信息
        result = f"Redis服务器信息 ({host}:{port}):\n"
        result += f"  Redis版本: {info.get('redis_version', 'Unknown')}\n"
        result += f"  运行模式: {info.get('redis_mode', 'Unknown')}\n"
        result += f"  已连接客户端数: {info.get('connected_clients', 'Unknown')}\n"
        result += f"  已使用内存: {info.get('used_memory_human', 'Unknown')}\n"
        result += f"  运行时间: {info.get('uptime_in_seconds', 'Unknown')} 秒\n"
        result += f"  总命令数: {info.get('total_commands_processed', 'Unknown')}\n"
        result += f"  键空间命中率: {info.get('keyspace_hits', 0) / max(info.get('keyspace_hits', 0) + info.get('keyspace_misses', 0), 1) * 100:.2f}%"
        
        return result
        
    except Exception as e:
        return f"获取Redis信息失败: {str(e)}"

@mcp.tool()
def redis_ping_simple() -> str:
    """测试Redis连接（使用默认配置）
    
    返回:
        str: 连接测试结果
    """
    try:
        config = DEFAULT_REDIS_CONFIG
        redis_conn = get_redis_connection(config["host"], config["port"], config["password"], config["db"])
        result = redis_conn.ping()
        
        if result:
            return f"Redis服务器 {config['host']}:{config['port']} 连接正常"
        else:
            return f"Redis服务器 {config['host']}:{config['port']} 连接异常"
            
    except Exception as e:
        return f"Redis连接测试失败: {str(e)}"

@mcp.tool()
def redis_set_simple(key: str, value: str, expire: Optional[int] = None) -> str:
    """设置Redis键值对（使用默认配置）
    
    参数:
        key (str): 键名
        value (str): 值
        expire (int, optional): 过期时间（秒）
    
    返回:
        str: 操作结果信息
    """
    try:
        config = DEFAULT_REDIS_CONFIG
        redis_conn = get_redis_connection(config["host"], config["port"], config["password"], config["db"])
        
        if expire:
            result = redis_conn.setex(key, expire, value)
        else:
            result = redis_conn.set(key, value)
        
        if result:
            return f"成功设置键 '{key}' = '{value}'" + (f" (过期时间: {expire}秒)" if expire else "")
        else:
            return f"设置键 '{key}' 失败"
            
    except Exception as e:
        return f"设置键值对失败: {str(e)}"

@mcp.tool()
def redis_get_simple(key: str) -> str:
    """获取Redis键值（使用默认配置）
    
    参数:
        key (str): 键名
    
    返回:
        str: 键值或错误信息
    """
    try:
        config = DEFAULT_REDIS_CONFIG
        redis_conn = get_redis_connection(config["host"], config["port"], config["password"], config["db"])
        value = redis_conn.get(key)
        
        if value is not None:
            return f"键 '{key}' 的值: {value}"
        else:
            return f"键 '{key}' 不存在"
            
    except Exception as e:
        return f"获取键值失败: {str(e)}"

@mcp.tool()
def redis_delete_simple(key: str) -> str:
    """删除Redis键（使用默认配置）
    
    参数:
        key (str): 键名
    
    返回:
        str: 操作结果信息
    """
    try:
        config = DEFAULT_REDIS_CONFIG
        redis_conn = get_redis_connection(config["host"], config["port"], config["password"], config["db"])
        result = redis_conn.delete(key)
        
        if result > 0:
            return f"成功删除键 '{key}'"
        else:
            return f"键 '{key}' 不存在或已被删除"
            
    except Exception as e:
        return f"删除键失败: {str(e)}"

@mcp.tool()
def redis_keys_simple(pattern: str = "*") -> str:
    """获取匹配模式的Redis键列表（使用默认配置）
    
    参数:
        pattern (str): 键名模式，默认为"*"（所有键）
    
    返回:
        str: 匹配的键列表
    """
    try:
        config = DEFAULT_REDIS_CONFIG
        redis_conn = get_redis_connection(config["host"], config["port"], config["password"], config["db"])
        keys = redis_conn.keys(pattern)
        
        if keys:
            return f"匹配模式 '{pattern}' 的键: {', '.join(keys)}"
        else:
            return f"没有找到匹配模式 '{pattern}' 的键"
            
    except Exception as e:
        return f"获取键列表失败: {str(e)}"

@mcp.tool()
def redis_info_simple() -> str:
    """获取Redis服务器信息（使用默认配置）
    
    返回:
        str: Redis服务器信息
    """
    try:
        config = DEFAULT_REDIS_CONFIG
        redis_conn = get_redis_connection(config["host"], config["port"], config["password"], config["db"])
        info = redis_conn.info()
        
        # 格式化输出重要信息
        result = f"Redis服务器信息 ({config['host']}:{config['port']}):\n"
        result += f"  Redis版本: {info.get('redis_version', 'Unknown')}\n"
        result += f"  运行模式: {info.get('redis_mode', 'Unknown')}\n"
        result += f"  已连接客户端数: {info.get('connected_clients', 'Unknown')}\n"
        result += f"  已使用内存: {info.get('used_memory_human', 'Unknown')}\n"
        result += f"  运行时间: {info.get('uptime_in_seconds', 'Unknown')} 秒\n"
        result += f"  总命令数: {info.get('total_commands_processed', 'Unknown')}\n"
        result += f"  键空间命中率: {info.get('keyspace_hits', 0) / max(info.get('keyspace_hits', 0) + info.get('keyspace_misses', 0), 1) * 100:.2f}%"
        
        return result
        
    except Exception as e:
        return f"获取Redis信息失败: {str(e)}"

# ==================== 高级交互式工具 ====================
# 这些工具与prompts配合使用，提供更好的用户体验

@mcp.tool()
def redis_health_check() -> str:
    """Redis健康检查
    执行全面的Redis健康检查，包括连接、内存、性能等
    
    返回:
        str: 健康检查报告
    """
    try:
        config = DEFAULT_REDIS_CONFIG
        redis_conn = get_redis_connection(config["host"], config["port"], config["password"], config["db"])
        
        # 基本连接测试
        ping_result = redis_conn.ping()
        if not ping_result:
            return "❌ Redis连接失败"
        
        # 获取服务器信息
        info = redis_conn.info()
        
        # 健康检查报告
        report = "🔍 Redis健康检查报告\n"
        report += "=" * 50 + "\n"
        
        # 连接状态
        report += "✅ 连接状态: 正常\n"
        report += f"📍 服务器: {config['host']}:{config['port']}\n"
        report += f"🗄️ 数据库: {config['db']}\n\n"
        
        # 内存使用
        used_memory = info.get('used_memory_human', 'Unknown')
        max_memory = info.get('maxmemory_human', 'No limit')
        report += f"💾 内存使用: {used_memory}\n"
        report += f"📊 内存限制: {max_memory}\n"
        
        # 性能指标
        total_commands = info.get('total_commands_processed', 0)
        connected_clients = info.get('connected_clients', 0)
        report += f"⚡ 总命令数: {total_commands:,}\n"
        report += f"👥 连接客户端: {connected_clients}\n"
        
        # 键空间信息
        keyspace_hits = info.get('keyspace_hits', 0)
        keyspace_misses = info.get('keyspace_misses', 0)
        total_requests = keyspace_hits + keyspace_misses
        hit_rate = (keyspace_hits / total_requests * 100) if total_requests > 0 else 0
        report += f"🎯 命中率: {hit_rate:.2f}%\n"
        
        # 运行时间
        uptime = info.get('uptime_in_seconds', 0)
        days = uptime // 86400
        hours = (uptime % 86400) // 3600
        minutes = (uptime % 3600) // 60
        report += f"⏰ 运行时间: {days}天 {hours}小时 {minutes}分钟\n"
        
        # 健康状态评估
        report += "\n🏥 健康状态评估:\n"
        if hit_rate > 90:
            report += "✅ 缓存命中率优秀\n"
        elif hit_rate > 70:
            report += "⚠️ 缓存命中率良好\n"
        else:
            report += "❌ 缓存命中率需要优化\n"
            
        if connected_clients < 100:
            report += "✅ 连接数正常\n"
        else:
            report += "⚠️ 连接数较高，建议检查\n"
            
        return report
        
    except Exception as e:
        return f"❌ 健康检查失败: {str(e)}"

@mcp.tool()
def redis_data_audit() -> str:
    """Redis数据审计
    分析Redis中的数据分布、过期时间、内存使用等
    
    返回:
        str: 数据审计报告
    """
    try:
        config = DEFAULT_REDIS_CONFIG
        redis_conn = get_redis_connection(config["host"], config["port"], config["password"], config["db"])
        
        # 获取所有键
        all_keys = redis_conn.keys("*")
        
        if not all_keys:
            return "📊 数据审计报告\n" + "=" * 30 + "\n\n📭 数据库为空，没有数据需要审计。"
        
        # 分析键模式
        key_patterns = {}
        expired_keys = []
        never_expire_keys = []
        
        for key in all_keys:
            # 分析键模式
            if ':' in key:
                pattern = key.split(':')[0] + ':*'
            else:
                pattern = 'simple_keys'
            
            key_patterns[pattern] = key_patterns.get(pattern, 0) + 1
            
            # 检查过期时间
            ttl = redis_conn.ttl(key)
            if ttl == -1:
                never_expire_keys.append(key)
            elif ttl == -2:
                expired_keys.append(key)
        
        # 生成审计报告
        report = "📊 Redis数据审计报告\n"
        report += "=" * 50 + "\n"
        report += f"📈 总键数: {len(all_keys)}\n"
        report += f"⏰ 永不过期键: {len(never_expire_keys)}\n"
        report += f"💀 已过期键: {len(expired_keys)}\n\n"
        
        # 键模式分析
        report += "🔍 键模式分析:\n"
        for pattern, count in sorted(key_patterns.items(), key=lambda x: x[1], reverse=True):
            percentage = (count / len(all_keys)) * 100
            report += f"  {pattern}: {count} ({percentage:.1f}%)\n"
        
        # 内存使用分析
        info = redis_conn.info()
        used_memory = info.get('used_memory_human', 'Unknown')
        report += f"\n💾 内存使用: {used_memory}\n"
        
        # 建议
        report += "\n💡 优化建议:\n"
        if len(never_expire_keys) > len(all_keys) * 0.5:
            report += "⚠️ 超过50%的键没有设置过期时间，建议为缓存数据设置TTL\n"
        
        if len(expired_keys) > 0:
            report += "🧹 发现已过期但未清理的键，建议定期清理\n"
        
        if len(all_keys) > 10000:
            report += "📊 键数量较多，建议考虑数据分片或清理无用数据\n"
        
        return report
        
    except Exception as e:
        return f"❌ 数据审计失败: {str(e)}"

@mcp.tool()
def redis_performance_test(operations: int = 100) -> str:
    """Redis性能测试
    执行Redis性能测试，包括SET、GET、HSET等操作
    
    参数:
        operations (int): 测试操作数量，默认100
    
    返回:
        str: 性能测试报告
    """
    try:
        config = DEFAULT_REDIS_CONFIG
        redis_conn = get_redis_connection(config["host"], config["port"], config["password"], config["db"])
        
        import time
        
        report = "⚡ Redis性能测试报告\n"
        report += "=" * 40 + "\n"
        report += f"🔢 测试操作数: {operations}\n\n"
        
        # SET操作测试
        start_time = time.time()
        for i in range(operations):
            redis_conn.set(f"perf_test:set:{i}", f"value_{i}")
        set_time = time.time() - start_time
        set_ops_per_sec = operations / set_time
        
        # GET操作测试
        start_time = time.time()
        for i in range(operations):
            redis_conn.get(f"perf_test:set:{i}")
        get_time = time.time() - start_time
        get_ops_per_sec = operations / get_time
        
        # HSET操作测试
        start_time = time.time()
        for i in range(operations):
            redis_conn.hset(f"perf_test:hash:{i}", "field", f"value_{i}")
        hset_time = time.time() - start_time
        hset_ops_per_sec = operations / hset_time
        
        # HGET操作测试
        start_time = time.time()
        for i in range(operations):
            redis_conn.hget(f"perf_test:hash:{i}", "field")
        hget_time = time.time() - start_time
        hget_ops_per_sec = operations / hget_time
        
        # 生成报告
        report += f"📝 SET操作: {set_ops_per_sec:.0f} ops/sec ({set_time:.3f}s)\n"
        report += f"📖 GET操作: {get_ops_per_sec:.0f} ops/sec ({get_time:.3f}s)\n"
        report += f"📝 HSET操作: {hset_ops_per_sec:.0f} ops/sec ({hset_time:.3f}s)\n"
        report += f"📖 HGET操作: {hget_ops_per_sec:.0f} ops/sec ({hget_time:.3f}s)\n"
        
        # 性能评估
        report += "\n🏆 性能评估:\n"
        if set_ops_per_sec > 10000:
            report += "✅ SET性能优秀\n"
        elif set_ops_per_sec > 5000:
            report += "⚠️ SET性能良好\n"
        else:
            report += "❌ SET性能需要优化\n"
            
        if get_ops_per_sec > 15000:
            report += "✅ GET性能优秀\n"
        elif get_ops_per_sec > 8000:
            report += "⚠️ GET性能良好\n"
        else:
            report += "❌ GET性能需要优化\n"
        
        # 清理测试数据
        for i in range(operations):
            redis_conn.delete(f"perf_test:set:{i}")
            redis_conn.delete(f"perf_test:hash:{i}")
        
        report += "\n🧹 测试数据已清理"
        
        return report
        
    except Exception as e:
        return f"❌ 性能测试失败: {str(e)}"

@mcp.tool()
def redis_batch_operations(operation_type: str, keys: List[str], values: List[str] = None) -> str:
    """Redis批量操作
    执行批量Redis操作，提高效率
    
    参数:
        operation_type (str): 操作类型，可选值：set, get, delete, exists
        keys (List[str]): 键列表
        values (List[str], optional): 值列表（仅用于set操作）
    
    返回:
        str: 批量操作结果
    """
    try:
        config = DEFAULT_REDIS_CONFIG
        redis_conn = get_redis_connection(config["host"], config["port"], config["password"], config["db"])
        
        if not keys:
            return "❌ 键列表不能为空"
        
        results = []
        
        if operation_type == "set":
            if not values or len(values) != len(keys):
                return "❌ SET操作需要提供与键数量相等的值"
            
            for key, value in zip(keys, values):
                result = redis_conn.set(key, value)
                results.append(f"✅ {key} = {value}")
        
        elif operation_type == "get":
            for key in keys:
                value = redis_conn.get(key)
                if value:
                    results.append(f"📖 {key}: {value}")
                else:
                    results.append(f"❌ {key}: 不存在")
        
        elif operation_type == "delete":
            for key in keys:
                result = redis_conn.delete(key)
                if result:
                    results.append(f"🗑️ 已删除: {key}")
                else:
                    results.append(f"❌ 删除失败: {key}")
        
        elif operation_type == "exists":
            for key in keys:
                exists = redis_conn.exists(key)
                status = "存在" if exists else "不存在"
                results.append(f"🔍 {key}: {status}")
        
        else:
            return f"❌ 不支持的操作类型: {operation_type}"
        
        # 生成报告
        report = f"📦 批量{operation_type.upper()}操作结果\n"
        report += "=" * 40 + "\n"
        report += f"🔢 操作数量: {len(keys)}\n"
        report += f"✅ 成功: {len([r for r in results if '✅' in r or '📖' in r or '🗑️' in r or '存在' in r])}\n"
        report += f"❌ 失败: {len([r for r in results if '❌' in r])}\n\n"
        
        for result in results:
            report += f"{result}\n"
        
        return report
        
    except Exception as e:
        return f"❌ 批量操作失败: {str(e)}"

@mcp.tool()
def redis_ping(host: str, port: int, password: Optional[str] = None, db: int = 0) -> str:
    """测试Redis连接
    
    参数:
        host (str): Redis服务器地址
        port (int): Redis服务器端口
        password (str, optional): Redis密码
        db (int): 数据库编号，默认为0
    
    返回:
        str: 连接测试结果
    """
    try:
        redis_conn = get_redis_connection(host, port, password, db)
        result = redis_conn.ping()
        
        if result:
            return f"Redis服务器 {host}:{port} 连接正常"
        else:
            return f"Redis服务器 {host}:{port} 连接异常"
            
    except Exception as e:
        return f"Redis连接测试失败: {str(e)}"

# ==================== MCP PROMPTS ====================
# 使用 @mcp.prompt() 装饰器注册提示模板，提供更好的用户交互体验

@mcp.prompt()
def redis_quick_setup() -> str:
    """Redis快速设置向导
    帮助用户快速设置和测试Redis连接
    
    返回:
        str: Redis设置指导提示
    """
    return """
# Redis快速设置向导

请按照以下步骤设置Redis：

## 1. 检查Redis服务器状态
首先检查Redis服务器是否正在运行：
- 使用 `redis_ping_simple()` 测试连接
- 如果连接失败，请启动Redis服务器

## 2. 基本操作测试
测试基本的Redis操作：
- 设置一个测试键：`redis_set_simple("test", "hello")`
- 获取键值：`redis_get_simple("test")`
- 删除测试键：`redis_delete_simple("test")`

## 3. 查看Redis信息
使用 `redis_info_simple()` 查看Redis服务器状态

## 4. 常用操作模式
- **缓存模式**：使用 `redis_set_simple(key, value, expire=3600)` 设置带过期时间的缓存
- **会话存储**：使用哈希表存储用户会话信息
- **队列操作**：使用列表进行简单的队列操作

需要我帮你执行任何这些操作吗？
"""

@mcp.prompt()
def redis_data_analysis(operation_type: str = "overview") -> str:
    """Redis数据分析提示
    帮助用户分析Redis中的数据
    
    参数:
        operation_type (str): 分析类型，可选值：
            - "overview": 概览分析
            - "keys": 键分析
            - "memory": 内存分析
            - "performance": 性能分析
    
    返回:
        str: 数据分析指导提示
    """
    prompts = {
        "overview": """
# Redis数据概览分析

让我们全面了解你的Redis数据库：

## 1. 获取所有键
使用 `redis_keys_simple("*")` 查看所有键

## 2. 分析键模式
- 查看特定模式的键：`redis_keys_simple("user:*")`
- 查看缓存键：`redis_keys_simple("*cache*")`
- 查看会话键：`redis_keys_simple("session:*")`

## 3. 检查键的生存时间
对重要键使用 `redis_ttl(host, port, key)` 检查过期时间

## 4. 服务器状态
使用 `redis_info_simple()` 获取详细的服务器信息

你想从哪个方面开始分析？
""",
        
        "keys": """
# Redis键分析

深入分析Redis中的键：

## 1. 键统计
- 总键数：`redis_keys_simple("*")` 然后计算数量
- 按模式分组：`redis_keys_simple("user:*")`, `redis_keys_simple("cache:*")` 等

## 2. 键值分析
- 检查重要键的值：`redis_get_simple("important_key")`
- 分析哈希表：`redis_hgetall(host, port, "hash_table_name")`
- 查看列表内容：`redis_lrange(host, port, "list_name", 0, -1)`

## 3. 过期时间分析
- 检查键的TTL：`redis_ttl(host, port, key)`
- 识别永不过期的键

## 4. 数据清理建议
基于分析结果，建议清理策略

需要我帮你执行具体的分析步骤吗？
""",
        
        "memory": """
# Redis内存分析

分析Redis内存使用情况：

## 1. 服务器内存信息
使用 `redis_info_simple()` 获取：
- 已使用内存 (used_memory_human)
- 内存峰值 (used_memory_peak_human)
- 内存碎片率 (mem_fragmentation_ratio)

## 2. 键空间分析
- 分析不同数据库的键分布
- 识别占用内存最多的键类型

## 3. 内存优化建议
- 设置合理的过期时间
- 使用适当的数据结构
- 定期清理无用数据

## 4. 监控建议
- 设置内存使用告警
- 定期检查内存增长趋势

需要我帮你获取具体的内存信息吗？
""",
        
        "performance": """
# Redis性能分析

分析Redis性能指标：

## 1. 基本性能指标
使用 `redis_info_simple()` 获取：
- 总命令数 (total_commands_processed)
- 键空间命中率 (keyspace_hits/keyspace_misses)
- 连接数 (connected_clients)

## 2. 操作性能测试
- 测试SET操作性能
- 测试GET操作性能
- 测试复杂查询性能

## 3. 性能优化建议
- 优化数据结构选择
- 使用管道批量操作
- 合理设置连接池

## 4. 监控设置
- 设置性能监控
- 建立性能基线

需要我帮你进行性能测试吗？
"""
    }
    
    return prompts.get(operation_type, prompts["overview"])

@mcp.prompt()
def redis_workflow_guide(workflow_type: str = "caching") -> str:
    """Redis工作流指导
    提供常见Redis使用场景的完整工作流
    
    参数:
        workflow_type (str): 工作流类型，可选值：
            - "caching": 缓存工作流
            - "session": 会话管理
            - "queue": 队列处理
            - "counter": 计数器
            - "leaderboard": 排行榜
    
    返回:
        str: 工作流指导提示
    """
    workflows = {
        "caching": """
# Redis缓存工作流

## 1. 设置缓存
```python
# 设置带过期时间的缓存
redis_set_simple("user:123", "user_data", expire=3600)  # 1小时过期
redis_set_simple("product:456", "product_info", expire=1800)  # 30分钟过期
```

## 2. 获取缓存
```python
# 获取缓存数据
user_data = redis_get_simple("user:123")
product_info = redis_get_simple("product:456")
```

## 3. 缓存策略
- **热点数据**：设置较长过期时间
- **冷数据**：设置较短过期时间
- **实时数据**：不设置过期时间，手动更新

## 4. 缓存更新
- 数据更新时同时更新缓存
- 使用版本号避免缓存冲突

## 5. 缓存清理
```python
# 删除特定缓存
redis_delete_simple("user:123")
# 批量删除
redis_keys_simple("user:*")  # 先查看，再批量删除
```

需要我帮你实现具体的缓存操作吗？
""",
        
        "session": """
# Redis会话管理工作流

## 1. 创建会话
```python
# 使用哈希表存储会话信息
redis_hset(host, port, "session:abc123", "user_id", "12345")
redis_hset(host, port, "session:abc123", "username", "john_doe")
redis_hset(host, port, "session:abc123", "login_time", "2024-01-01 10:00:00")
```

## 2. 获取会话信息
```python
# 获取完整会话信息
session_data = redis_hgetall(host, port, "session:abc123")
# 获取特定字段
user_id = redis_hget(host, port, "session:abc123", "user_id")
```

## 3. 更新会话
```python
# 更新最后活动时间
redis_hset(host, port, "session:abc123", "last_activity", "2024-01-01 11:00:00")
```

## 4. 会话过期
```python
# 设置会话过期时间
redis_set_simple("session:abc123", "active", expire=1800)  # 30分钟
```

## 5. 会话清理
```python
# 删除过期会话
redis_delete_simple("session:abc123")
```

需要我帮你管理具体的会话吗？
""",
        
        "queue": """
# Redis队列处理工作流

## 1. 创建队列
```python
# 向队列添加任务
redis_lpush(host, port, "task_queue", "task1", "task2", "task3")
```

## 2. 处理队列
```python
# 从队列获取任务
task = redis_rpop(host, port, "task_queue")
```

## 3. 队列监控
```python
# 查看队列长度
queue_length = redis_lrange(host, port, "task_queue", 0, -1)
```

## 4. 优先级队列
```python
# 高优先级任务
redis_lpush(host, port, "high_priority_queue", "urgent_task")
# 普通任务
redis_lpush(host, port, "normal_queue", "normal_task")
```

## 5. 队列状态
```python
# 检查队列是否为空
tasks = redis_lrange(host, port, "task_queue", 0, -1)
if not tasks:
    print("队列为空")
```

需要我帮你处理具体的队列操作吗？
""",
        
        "counter": """
# Redis计数器工作流

## 1. 简单计数器
```python
# 初始化计数器
redis_set_simple("page_views", "0")
# 增加计数
current = int(redis_get_simple("page_views").split(": ")[1])
redis_set_simple("page_views", str(current + 1))
```

## 2. 多维度计数
```python
# 按页面计数
redis_hset(host, port, "page_stats", "home", "1000")
redis_hset(host, port, "page_stats", "about", "500")
```

## 3. 实时统计
```python
# 获取所有统计数据
stats = redis_hgetall(host, port, "page_stats")
```

## 4. 计数器重置
```python
# 重置特定计数器
redis_set_simple("page_views", "0")
# 重置所有计数器
redis_delete_simple("page_stats")
```

## 5. 计数器过期
```python
# 设置每日重置
redis_set_simple("daily_views", "0", expire=86400)  # 24小时
```

需要我帮你设置具体的计数器吗？
""",
        
        "leaderboard": """
# Redis排行榜工作流

## 1. 分数存储
```python
# 使用有序集合存储分数
# 注意：这里需要Redis的有序集合命令，当前MCP可能需要扩展
redis_set_simple("player:user1", "1000")
redis_set_simple("player:user2", "1500")
redis_set_simple("player:user3", "800")
```

## 2. 排名查询
```python
# 获取所有玩家分数
players = redis_keys_simple("player:*")
for player in players:
    score = redis_get_simple(player)
    print(f"{player}: {score}")
```

## 3. 分数更新
```python
# 更新玩家分数
redis_set_simple("player:user1", "1200")
```

## 4. 排行榜生成
```python
# 获取所有玩家并排序
players = redis_keys_simple("player:*")
scores = []
for player in players:
    score = redis_get_simple(player)
    scores.append((player, score))
scores.sort(key=lambda x: int(x[1]), reverse=True)
```

## 5. 定期重置
```python
# 每周重置排行榜
redis_delete_simple("player:*")  # 注意：这会删除所有玩家数据
```

需要我帮你实现具体的排行榜功能吗？
"""
    }
    
    return workflows.get(workflow_type, workflows["caching"])

@mcp.prompt()
def redis_troubleshooting() -> str:
    """Redis故障排除指南
    帮助用户诊断和解决Redis问题
    
    返回:
        str: 故障排除指导提示
    """
    return """
# Redis故障排除指南

## 1. 连接问题
**症状**：无法连接到Redis服务器
**诊断步骤**：
1. 检查Redis服务是否运行：`redis_ping_simple()`
2. 检查网络连接
3. 验证配置参数（host, port, password）

**解决方案**：
- 启动Redis服务
- 检查防火墙设置
- 验证连接参数

## 2. 内存问题
**症状**：Redis内存使用过高
**诊断步骤**：
1. 查看内存使用：`redis_info_simple()`
2. 分析键空间：`redis_keys_simple("*")`
3. 检查过期时间：`redis_ttl(host, port, key)`

**解决方案**：
- 设置合理的过期时间
- 清理无用数据
- 优化数据结构

## 3. 性能问题
**症状**：Redis响应缓慢
**诊断步骤**：
1. 检查服务器状态：`redis_info_simple()`
2. 分析命令执行情况
3. 检查网络延迟

**解决方案**：
- 优化查询模式
- 使用连接池
- 考虑数据分片

## 4. 数据丢失
**症状**：数据意外丢失
**诊断步骤**：
1. 检查持久化配置
2. 查看日志文件
3. 验证数据备份

**解决方案**：
- 启用RDB/AOF持久化
- 定期备份数据
- 监控数据完整性

## 5. 常见错误码
- **NOAUTH**：需要密码认证
- **WRONGTYPE**：数据类型不匹配
- **NOSCRIPT**：脚本不存在
- **BUSY**：服务器忙碌

需要我帮你诊断具体的问题吗？
"""

@mcp.prompt()
def redis_best_practices() -> str:
    """Redis最佳实践指南
    提供Redis使用的最佳实践建议
    
    返回:
        str: 最佳实践指导提示
    """
    return """
# Redis最佳实践指南

## 1. 数据结构选择
**字符串**：
- 简单键值对
- 计数器
- 缓存

**哈希表**：
- 对象存储
- 会话管理
- 配置信息

**列表**：
- 队列
- 时间线
- 最新记录

## 2. 键命名规范
- 使用有意义的命名空间：`user:123`, `product:456`
- 避免特殊字符
- 保持命名一致性

## 3. 过期时间设置
- 缓存数据：设置合理过期时间
- 会话数据：根据业务需求设置
- 临时数据：设置较短过期时间

## 4. 内存优化
- 使用适当的数据结构
- 定期清理无用数据
- 监控内存使用情况

## 5. 性能优化
- 使用管道批量操作
- 避免大键值对
- 合理使用连接池

## 6. 安全考虑
- 设置密码保护
- 限制网络访问
- 定期更新Redis版本

## 7. 监控和日志
- 监控关键指标
- 设置告警机制
- 保留操作日志

## 8. 备份策略
- 定期数据备份
- 测试恢复流程
- 多地域备份

需要我帮你实现任何最佳实践吗？
"""

if __name__ == "__main__":
    mcp.run(transport="stdio")
